package cn.rengy.web.framework.antireptile.rule;

import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

import cn.rengy.tool.web._WebUtils;
import cn.rengy.web.framework.antireptile.config.AntiReptileProperties;
import lombok.extern.slf4j.Slf4j;

/**
 */
@Slf4j
public class IpRule extends AbstractRule {


    @Autowired
    private AntiReptileProperties properties;
    private StringRedisTemplate stringRedisTemplate;
	@Autowired
	public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
		this.stringRedisTemplate = stringRedisTemplate;
	}
	private RedisTemplate<Object, Object> redisTemplate;
	@Autowired
	public void setRedisTemplate(RedisTemplate<Object, Object> redisTemplate) {
		this.redisTemplate = redisTemplate;
	}
    private static final String RATELIMITER_COUNT_PREFIX = "ratelimiter_request_count::";
    private static final String RATELIMITER_BLACKLIST = "ratelimiter_blacklist::";

    /**
     * 命中返回true
     */
    @Override
    protected boolean doExecute(HttpServletRequest request, HttpServletResponse response) {
        String ipAddress = _WebUtils.getClientIp(request);
        //白名单
        List<String> ignoreIpList = properties.getIpRule().getIgnoreIp();
        if (ignoreIpList != null && ignoreIpList.size() > 0){
        	boolean isWhiteList=false;
            for (String ignoreIp : ignoreIpList) {
                if (ignoreIp.endsWith("*")) {
                    ignoreIp = ignoreIp.substring(0, ignoreIp.length() - 1);
                }
                if (ipAddress.startsWith(ignoreIp)) {
                	isWhiteList =true;
                	break;
                }
            }
            if(!isWhiteList) {
            	return true;
            }
        }
        
        String requestUrl = request.getRequestURI();
        //String RequestURL=request.getRequestURL().toString();
        //String QueryString=request.getQueryString();
        // log.debug("getRequestURI={}",requestUrl);
        //log.debug("getRequestURL={}",RequestURL);
        //log.debug("getQueryString={}",QueryString);
        //毫秒，默认5000
        int expirationTime = properties.getIpRule().getExpirationTime();
        //最高expirationTime时间内请求数
        int requestMaxSize = properties.getIpRule().getRequestMaxSize();
        
        //访问一个接口超限限制访问所有接口
        String hitKey=RATELIMITER_BLACKLIST.concat(ipAddress);
        String isHit=stringRedisTemplate.opsForValue().get(hitKey);
        //1.查询黑名单
        if(isHit!=null) {
        	return true;
        }
        //2.计数
        String countKey=RATELIMITER_COUNT_PREFIX.concat(requestUrl).concat("::").concat(ipAddress);
        Long accessCount=redisTemplate.opsForValue().increment(countKey);
        if(accessCount>requestMaxSize){
        	log.info("{}加入黑名单",ipAddress);
        	//加入黑名单
        	long lockExpire = properties.getIpRule().getLockExpire();
        	stringRedisTemplate.opsForValue().set(hitKey, "0", Duration.ofSeconds(lockExpire));
        	return true;
        }
        Long countExpire=redisTemplate.getExpire(countKey);
        if(countExpire==-1) {
        	redisTemplate.expire(countKey, expirationTime, TimeUnit.MILLISECONDS);
        }
        return false;
    }

    /**
     * 重置已记录规则
     * @param request 请求
     * @param realRequestUri 原始请求uri
     */
    @Override
    public void reset(HttpServletRequest request, String realRequestUri) {
        
    }


    @Override
    public int getOrder() {
        return 0;
    }
}
